package algorithm1_v2;

import java.io.ObjectInputStream;
import java.lang.management.ManagementFactory;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Task2 implements Callable<Object> {
//	class Message {
//		String leader;
//		String process;
//		Map<String, Integer> recovered;
//
//		Message(String leader, String process, Map<String, Integer> recovered) {
//			this.leader = leader;
//			this.process = process;
//			this.recovered = recovered;
//		}
//	}

	@Override
	public Object call() throws Exception {
		SystemInfo info = SystemInfo.INSTANCE;
		ServerSocket serverSocket = null;
		ScheduledExecutorService task3 = Executors
				.newSingleThreadScheduledExecutor();
		if (info.leader.toString().compareTo(
				ManagementFactory.getRuntimeMXBean().getName()) != 0) {
			task3.schedule(new Task3(), info.timeout.get(info.leader),
					TimeUnit.MILLISECONDS);
		}
		try {
			serverSocket = new ServerSocket(12345);
			Socket clientSocket = serverSocket.accept();
			while (true) {
				ObjectInputStream clientInputStream = new ObjectInputStream(
						clientSocket.getInputStream());
				Message message = (Message) clientInputStream.readObject();
				for (String entry : message.recovered.keySet()) {
					info.recovered.put(entry, Math.max(
							info.recovered.get(entry),
							message.recovered.get(entry)));
				}
				info.candidates.put(message.process.toString(), "");
				UpdateLeader.update();
				task3.shutdown();
				task3 = Executors.newSingleThreadScheduledExecutor();
				task3.schedule(new Task3(), info.timeout.get(info.leader),
						TimeUnit.MILLISECONDS);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				serverSocket.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		return null;
	}
}
